#include "StdAfx.h"
#include "GameFrameListener.h"

GameFrameListener::GameFrameListener(Ogre::RenderWindow* pOgreWin)
:	m_pOgreWin(pOgreWin), m_bQuit(false), 
	m_pUI(NULL), m_pCameraMgr(NULL)
{
	// ------init input system------
	OIS::ParamList ois_param_list;
	size_t window_hnd = 0;
	std::ostringstream window_hnd_str;
	// get window handl
	pOgreWin->getCustomAttribute("WINDOW", &window_hnd);
	// fill param list
	window_hnd_str<<(Ogre::uint32)window_hnd;
	ois_param_list.insert(std::make_pair(std::string("WINDOW"), window_hnd_str.str()));

	m_pOISMgr = OIS::InputManager::createInputSystem(ois_param_list);
	// ~~~init mouse~~~
	if(m_pOISMgr->getNumberOfDevices(OIS::OISMouse) > 0)
	{
		m_pOISMouse = static_cast<OIS::Mouse*>(m_pOISMgr->createInputObject(OIS::OISMouse, true));
		m_pOISMouse->setEventCallback(this);

		Ogre::uint32 width, height, depth;
		Ogre::int32 left, top;
		pOgreWin->getMetrics(width, height, depth, left, top);
		
		const OIS::MouseState& mouseState = m_pOISMouse->getMouseState();
		mouseState.width = width;
		mouseState.height = height;
	}
	// ~~~init keyboard~~~
	if(m_pOISMgr->getNumberOfDevices(OIS::OISKeyboard) > 0)
	{
		m_pOISKeyboard = static_cast<OIS::Keyboard*>(m_pOISMgr->createInputObject(OIS::OISKeyboard, true));
		m_pOISKeyboard->setEventCallback(this);
	}
}

GameFrameListener::~GameFrameListener(void)
{
}

bool GameFrameListener::frameStarted(const Ogre::FrameEvent& evt)
{
	if(m_pOgreWin->isClosed() || m_bQuit)
		return false;

	// always inject a time pulse to enable widget automation
	m_pUISystem->injectTimePulse(static_cast<float>(evt.timeSinceLastFrame));

	if(m_pOISMouse)
		m_pOISMouse->capture();
	if(m_pOISKeyboard)
		m_pOISKeyboard->capture();
	if(m_pCameraMgr)
		m_pCameraMgr->frameStarted(evt);
	return true;
}
//bool GameFrameListener::processUnbufferedMouseInput(const FrameEvent& evt)
//{
//	const OIS::MouseState& ms = mMouse->getMouseState();
//	m_pUISystem->injectMouseMove(ms.X.rel, ms.Y.rel);
//	if(ms.buttonDown(OIS::MB_Right))
//		m_pUISystem->injectMouseButtonDown(CEGUI::RightButton);
//	if(ms.buttonDown(OIS::MB_Left))
//		m_pUISystem->injectMouseButtonDown(CEGUI::LeftButton);
//
//	return ExampleFrameListener::processUnbufferedMouseInput(evt);
//}

void GameFrameListener::setUIBase(UIBase* pUI)
{
	m_pUI = pUI;
	m_pUISystem = pUI->getSystem();
}

void GameFrameListener::setCameraManager(CameraManager* pCamMgr)
{
	m_pCameraMgr = pCamMgr;
}

bool GameFrameListener::mouseMoved(const OIS::MouseEvent &arg)
{
	m_pUISystem->injectMouseMove(arg.state.X.rel, arg.state.Y.rel);
	m_pUISystem->injectMouseWheelChange(arg.state.Z.rel / 120.0f);
	if(m_pCameraMgr)
		m_pCameraMgr->mouseMoved(arg);
	return true;
}

CEGUI::MouseButton GameFrameListener::convertOISButtonToCEGUI(int buttonID)
{
	switch (buttonID)
	{
	case OIS::MB_Left:
		return CEGUI::LeftButton;
	case OIS::MB_Right:
		return CEGUI::RightButton;
	case OIS::MB_Middle:
		return CEGUI::MiddleButton;
	default:
		return CEGUI::LeftButton;
	}
}

bool GameFrameListener::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	m_pUISystem->injectMouseButtonDown(convertOISButtonToCEGUI(id));
	if(m_pCameraMgr)
		m_pCameraMgr->mousePressed(arg, id);
	return true;
}

bool GameFrameListener::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	m_pUISystem->injectMouseButtonUp(convertOISButtonToCEGUI(id));
	if(m_pCameraMgr)
		m_pCameraMgr->mouseReleased(arg, id);
	return true;
}

bool GameFrameListener::keyPressed(const OIS::KeyEvent& e)
{
	if(e.key == OIS::KC_ESCAPE)
	{
		m_bQuit = true;
		return true;
	}
	if(e.key == OIS::KC_F5 && m_pUI)
	{
		m_pUI->reload();
	}
	m_pUISystem->injectKeyDown(e.key);
	m_pUISystem->injectChar(e.key);
	if(m_pCameraMgr)
		m_pCameraMgr->keyPressed(e);
	return true;
}

bool GameFrameListener::keyReleased(const OIS::KeyEvent& e)
{
	m_pUISystem->injectKeyUp(e.key);
	if(m_pCameraMgr)
		m_pCameraMgr->keyReleased(e);
	return true;
}